﻿// ....................................................................................................................
//	Author: Copyright (C) 2012 Ing. Marek Hubal
//	Email: hubal@acasoftware.org
// ....................................................................................................................

using System;

namespace core
{
    /// <summary>Trieda INodeList_ROOT</summary>
    public class INodeList_ROOT : INodeList
    {
        protected System.IO.DriveInfo[] FExpand_Drives; // Premenne pre expandovanie
        protected int FExpand_DriveIndex;
        protected int FExpand_Mode;

        /// <summary>Otvorenie cache pre zapis</summary>
        /// <param name="pCacheID">ID cache</param>
        /// <returns>true / false</returns>
        protected override bool BeginWriteCache(string pCacheID)
        {
            return false;
        }

        /// <summary>Konstruktor</summary>
        public INodeList_ROOT()
        {
            // Inicializacia
            ID = NODE_LIST_ID_ROOT;
            FColsCount = 4;
            FEnableVisibilityMask = 0xe; FDefVisibilityMask = 0xf;
            FThreadExpandAvailable = false;
            FHasBackItem = false;
        }

        /// <summary>Ziskanie nazvu stlpca</summary>
        /// <param name="pIndex">pozicia</param>
        /// <returns>nazov alebo prazdny retazec</returns>
        public override string GetColumnName(int pIndex)
        {
            switch(pIndex) {
                case 0: return lang.NODE_LIST_ROOT_TEXT_1;
                case 1: return lang.NODE_LIST_ROOT_TEXT_2;
                case 2: return lang.NODE_LIST_ROOT_TEXT_3;
                case 3: return lang.NODE_LIST_ROOT_TEXT_4;
                default: return "";
            }
        }
        /// <summary>Ziskanie zarovnania stlpca</summary>
        /// <param name="pIndex">pozicia</param>
        /// <returns>zarovnanie</returns>
        public override System.Windows.Forms.HorizontalAlignment GetColumnAlignment(int pIndex)
        {
            switch(pIndex) {
                case 2:
                case 3:
                    return System.Windows.Forms.HorizontalAlignment.Right;
                default: return System.Windows.Forms.HorizontalAlignment.Left;
            }
        }
        /// <summary>Test ci sa node moze expandovat</summary>
        /// <param name="pIndex">pozicia</param>
        /// <returns>true / false</returns>
        public override bool CanNodeExpand(int pIndex)
        {
            INode N = this[pIndex];
            if (N == null) return false; // Ziskam platny node

            switch (N.ID)
            {
                case INode.NODE_ID_LOCAL_DRIVE: 
                case INode.NODE_ID_SMB_ROOT:
                case INode.NODE_ID_CLOUD_DEVICES:
                    return true;
                default: return false;
            }
        }
        /// <summary>Ziskanie expandovacej cesty node</summary>
        /// <param name="pIndex">pozicia</param>
        /// <returns>cesta</returns>
        public override string GetNodeExpandPath(int pIndex)
        {
            INode N = this[pIndex];
            if (N == null) return ""; // Ziskam platny node

            switch (N.ID)
            {
                case INode.NODE_ID_LOCAL_DRIVE: return ((INodeData_LOCAL_DRIVE)N.NodeData).DrvInfo.RootDirectory.ToString();
                case INode.NODE_ID_SMB_ROOT: return "\\\\";
                case INode.NODE_ID_CLOUD_DEVICES: return "web://";
                default: return "";
            }
        }
        /// <summary>Test ci je mozne skryt stlpec</summary>
        /// <param name="pIndex">pozicia</param>
        /// <returns>true / false</returns>
        public override bool CanHideColumn(int pIndex)
        {
            switch (pIndex)
            {
                case 0: return false;
                default: return true; 
            }
        }
        /// <summary>Test ci je node CD zariadenim</summary>
        /// <param name="pIndex">pozicia</param>
        /// <returns>true / false</returns>
        public override bool IsNodeCDDevice(int pIndex)
        {
            INode N = this[pIndex];
            return (N != null) && (N.ID == INode.NODE_ID_LOCAL_DRIVE) && (((INodeData_LOCAL_DRIVE)N.NodeData).DrvInfo.DriveType == System.IO.DriveType.CDRom);
        }

        /// <summary>Zaciatok expandovania obsahu</summary>
        /// <param name="pFilter">objekt filtra</param>
        /// <returns>0 alebo kod chyby</returns>
        public override int BeginExpand(INodeFilters pFilter = null)
        {
            FExpand_Drives = null; // Inicializacia
            FExpand_DriveIndex = -1;
            FExpand_Mode = 0;
            FState = 1; // Nastavim mode expand
            return 0;
        }
        /// <summary>Uzatvorenie aktualneho expandu</summary>
        public override void CloseExpand()
        {
            FExpand_Drives = null; // Uvolnim
            FState = 0; // Nastavim normalny mod
        }
        /// <summary>Expandovanie dalsieho zaznamu</summary>
        /// <param name="Result">ulozeny obsah najdeneho zaznamu alebo null ak sa ma zaznam pripojit do zoznamu</param>
        /// <returns>0 - ziaden dalsi zaznam, 1 - najdeny zaznam alebo kod chyby</returns>
        public override int ExpandNext(INodeFilters pFilter = null, INode Result = null)
        {
            try
            {
                while (true)
                {
                    switch (FExpand_Mode)
                    {
                        case 2:
                            {
                                INode N = Result == null ? new INode() : Result; // Vytvorim node
                                N.ID = INode.NODE_ID_CLOUD_DEVICES;
                                if (Result == null) AddNode(N);
                                FExpand_Mode = 3;
                                return 1;
                            }
                        case 1:
                            {
                                INode N = Result == null ? new INode() : Result; // Vytvorim node
                                N.ID = INode.NODE_ID_SMB_ROOT;
                                if (Result == null) AddNode(N);
                                FExpand_Mode = 2;
                                return 1;
                            }
                        case 0:
                            {
                                if (FExpand_Drives == null)
                                {
                                    try
                                    {
                                        FExpand_Drives = System.IO.DriveInfo.GetDrives();
                                        FExpand_DriveIndex = 0;
                                    }
                                    catch
                                    {
                                        return -1;
                                    }
                                }

                                if (FExpand_DriveIndex >= FExpand_Drives.Length)
                                {
                                    FExpand_Mode = 1;
                                    break;
                                }
                                INode N = Result == null ? new INode() : Result; // Vytvorim node
                                N.ID = INode.NODE_ID_LOCAL_DRIVE;
                                N.NodeData = new INodeData_LOCAL_DRIVE();
                                ((INodeData_LOCAL_DRIVE)N.NodeData).DrvInfo = FExpand_Drives[FExpand_DriveIndex++];
                                if (Result == null) AddNode(N);

                                return 1;
                            }
                        default: return 0;
                    }
                }
            }
            catch
            {
                return -1;
            }
        }
        /// <summary>Vytvorenie textov pre zobrazenie</summary>
        /// <param name="pNode">objekt node</param>
        public override void CreateDisplayStrings(INode pNode)
        {
            if (pNode.DisplayStrings != null) return; // Uz su vytvorenie?
            
            pNode.DisplayStrings = new string[ColsCount]; // Alokujem retazec
            switch (pNode.ID) // Podla typu node
            {
                case INode.NODE_ID_CLOUD_DEVICES:
                    {
                        pNode.DisplayStrings[0] = lang.NODE_LIST_ROOT_TEXT_10;
                        pNode.DefaultImageIndex = 7;
                    } break;
                case INode.NODE_ID_SMB_ROOT:
                    {
                        pNode.DisplayStrings[0] = lang.NODE_LIST_ROOT_TEXT_9;
                        pNode.DefaultImageIndex = 7;
                    } break;
                case INode.NODE_ID_LOCAL_DRIVE:
                    {
                        switch (((INodeData_LOCAL_DRIVE)pNode.NodeData).DrvInfo.DriveType)
                        {
                            case System.IO.DriveType.Network:
                                {
                                    pNode.DisplayStrings[0] = string.Format(lang.NODE_LIST_ROOT_TEXT_5_4, char.ToUpper(((INodeData_LOCAL_DRIVE)pNode.NodeData).DrvInfo.Name[0]));
                                    pNode.DisplayStrings[1] = lang.NODE_LIST_ROOT_TEXT_6_4;
                                    pNode.DisplayStrings[2] = "";
                                    pNode.DisplayStrings[3] = "";
                                    pNode.DefaultImageIndex = 5;
                                } break;
                            case System.IO.DriveType.Removable:
                                {
                                    bool IsFloppy = IFileSystem.IsFloppyDevice(((INodeData_LOCAL_DRIVE)pNode.NodeData).DrvInfo.Name);
                                    pNode.DisplayStrings[0] = string.Format(IsFloppy ? lang.NODE_LIST_ROOT_TEXT_5_5 : lang.NODE_LIST_ROOT_TEXT_5_3, char.ToUpper(((INodeData_LOCAL_DRIVE)pNode.NodeData).DrvInfo.Name[0]));
                                    pNode.DisplayStrings[1] = IsFloppy ? lang.NODE_LIST_ROOT_TEXT_6_5 : lang.NODE_LIST_ROOT_TEXT_6_3;
                                    try
                                    {
                                        pNode.DisplayStrings[2] = ICore.Size2String((ulong)((INodeData_LOCAL_DRIVE)pNode.NodeData).DrvInfo.TotalSize, IApp.Settings.FileExplorer_DisplaySizeMode);
                                        pNode.DisplayStrings[3] = ICore.Size2String((ulong)((INodeData_LOCAL_DRIVE)pNode.NodeData).DrvInfo.AvailableFreeSpace, IApp.Settings.FileExplorer_DisplaySizeMode);
                                    }
                                    catch
                                    {
                                        pNode.DisplayStrings[2] = "";
                                        pNode.DisplayStrings[3] = "";
                                    }
                                    pNode.DefaultImageIndex = IsFloppy ? 4 : 6;
                                } break;
                            case System.IO.DriveType.CDRom:
                                {
                                    pNode.DisplayStrings[0] = string.Format(lang.NODE_LIST_ROOT_TEXT_5_2, char.ToUpper(((INodeData_LOCAL_DRIVE)pNode.NodeData).DrvInfo.Name[0]));
                                    pNode.DisplayStrings[1] = lang.NODE_LIST_ROOT_TEXT_6_2;
                                    pNode.DisplayStrings[2] = "";
                                    pNode.DisplayStrings[3] = "";
                                    pNode.DefaultImageIndex = 2;
                                } break;
                            default:
                                {
                                    pNode.DisplayStrings[0] = string.Format(lang.NODE_LIST_ROOT_TEXT_5_1, char.ToUpper(((INodeData_LOCAL_DRIVE)pNode.NodeData).DrvInfo.Name[0]));
                                    pNode.DisplayStrings[1] = lang.NODE_LIST_ROOT_TEXT_6_1;
                                    try
                                    {
                                        pNode.DisplayStrings[2] = ICore.Size2String((ulong)((INodeData_LOCAL_DRIVE)pNode.NodeData).DrvInfo.TotalSize, IApp.Settings.FileExplorer_DisplaySizeMode);
                                        pNode.DisplayStrings[3] = ICore.Size2String((ulong)((INodeData_LOCAL_DRIVE)pNode.NodeData).DrvInfo.AvailableFreeSpace, IApp.Settings.FileExplorer_DisplaySizeMode);
                                    }
                                    catch
                                    {
                                        pNode.DisplayStrings[2] = "";
                                        pNode.DisplayStrings[3] = "";
                                    }
                                    pNode.DefaultImageIndex = 3;
                                } break;
                        }
                    } break;
            }
        }
        /// <summary>Vytvorenie textu pre plozku device menu</summary>
        /// <param name="pNode">node</param>
        /// <returns>text</returns>
        public string CreateDeviceMenuText(INode pNode)
        {
            switch (pNode.ID)
            {
                case INode.NODE_ID_LOCAL_DRIVE:
                    {
                        string Result;
                        switch (((INodeData_LOCAL_DRIVE)pNode.NodeData).DrvInfo.DriveType)
                        {
                            case System.IO.DriveType.Network:
                                {
                                    try
                                    {
                                        Result = string.Format(lang.NODE_LIST_ROOT_TEXT_8, string.Format(lang.NODE_LIST_ROOT_TEXT_5_4, "&" + char.ToUpper(((INodeData_LOCAL_DRIVE)pNode.NodeData).DrvInfo.Name[0])), ICore.Size2String((ulong)((INodeData_LOCAL_DRIVE)pNode.NodeData).DrvInfo.AvailableFreeSpace, 1, ""));
                                    }
                                    catch
                                    {
                                        return "";
                                    }
                                    pNode.DefaultImageIndex = 5;
                                } break;
                            case System.IO.DriveType.Removable:
                                {
                                    try
                                    {
                                        bool IsFloppy = IFileSystem.IsFloppyDevice(((INodeData_LOCAL_DRIVE)pNode.NodeData).DrvInfo.Name);
                                        if (!IsFloppy) Result = string.Format(lang.NODE_LIST_ROOT_TEXT_8, string.Format(lang.NODE_LIST_ROOT_TEXT_5_3, "&" + char.ToUpper(((INodeData_LOCAL_DRIVE)pNode.NodeData).DrvInfo.Name[0])), ICore.Size2String((ulong)((INodeData_LOCAL_DRIVE)pNode.NodeData).DrvInfo.AvailableFreeSpace, 1, ""));
                                        else Result = string.Format(lang.NODE_LIST_ROOT_TEXT_5_5, "&" + char.ToUpper(((INodeData_LOCAL_DRIVE)pNode.NodeData).DrvInfo.Name[0]));
                                        pNode.DefaultImageIndex = IsFloppy ? 4 : 6;
                                    }
                                    catch
                                    {
                                        return "";
                                    }
                                } break;
                            case System.IO.DriveType.CDRom:
                                {
                                    Result = string.Format(lang.NODE_LIST_ROOT_TEXT_5_2, "&" + char.ToUpper(((INodeData_LOCAL_DRIVE)pNode.NodeData).DrvInfo.Name[0]));
                                    pNode.DefaultImageIndex = 2;
                                } break;
                            default:
                                {
                                    try
                                    {
                                        Result = string.Format(lang.NODE_LIST_ROOT_TEXT_8, string.Format(lang.NODE_LIST_ROOT_TEXT_5_1, "&" + char.ToUpper(((INodeData_LOCAL_DRIVE)pNode.NodeData).DrvInfo.Name[0])), ICore.Size2String((ulong)((INodeData_LOCAL_DRIVE)pNode.NodeData).DrvInfo.AvailableFreeSpace, 1, ""));
                                    }
                                    catch
                                    {
                                        return "";
                                    }
                                    pNode.DefaultImageIndex = 3;
                                } break;
                        }
                        return Result;
                    }
                default: return "";
            }
        }
        /// <summary>Vytvorenie klonu zoznamu</summary>
        /// <returns>objekt zoznamu</returns>
        public override INodeList CloneList()
        {
            return new INodeList_ROOT();
        }

        /// <summary>Ziskanie root cesty na dalsie lokalne zariadenie v poradi</summary>
        /// <param name="pPath">root cesta zariadenia</param>
        /// <returns>root cesta dalsieho zariadenia</returns>
        public static string GetNextDeviceRootPath(string pPath)
        {
            using (INodeList_ROOT L = new INodeList_ROOT())
            {
                L.FullExpand();

                int i;
                for (i = 0; i < L.NodesCount; i++) // Prechadzam node
                {
                    INode N = L[i];
                    switch (N.ID)
                    {
                        case INode.NODE_ID_LOCAL_DRIVE:
                            break;
                        default: continue;
                    }
                    if (string.Compare(L.GetNodeExpandPath(i), pPath) == 0) break; // Nasiel som zadany?
                }
                if (i == L.NodesCount) return pPath; // Nenasiel som zadany?

                for (int j = i + 1; j < L.NodesCount; j++) // Prechadzam napravo do konca
                {
                    INode N = L[i];
                    switch (N.ID)
                    {
                        case INode.NODE_ID_LOCAL_DRIVE:
                            break;
                        default: continue;
                    }
                    return L.GetNodeExpandPath(j);
                }

                for (int j = 0; j <= i; j++) // Prechadzam zlava do i
                {
                    INode N = L[i];
                    switch (N.ID)
                    {
                        case INode.NODE_ID_LOCAL_DRIVE:
                            break;
                        default: continue;
                    }
                    return L.GetNodeExpandPath(j);
                }
                return pPath; // Vratim original
            }
        }
        /// <summary>Ziskanie root cesty na predchadzajuce lokalne zariadenie v poradi</summary>
        /// <param name="pPath">root cesta zariadenia</param>
        /// <returns>root cesta predchadzajuceho zariadenia</returns>
        public static string GetPrevDeviceRootPath(string pPath)
        {
            using (INodeList_ROOT L = new INodeList_ROOT())
            {
                L.FullExpand();

                int i;
                for (i = 0; i < L.NodesCount; i++) // Prechadzam node
                {
                    INode N = L[i];
                    switch (N.ID)
                    {
                        case INode.NODE_ID_LOCAL_DRIVE:
                            break;
                        default: continue;
                    }
                    if (string.Compare(L.GetNodeExpandPath(i), pPath) == 0) break; // Nasiel som zadany?
                }
                if (i == L.NodesCount) return pPath; // Nenasiel som zadany?

                for (int j = i - 1; j >= 0; j--) // Prechadzam nalavo do zaciatku
                {
                    INode N = L[i];
                    switch (N.ID)
                    {
                        case INode.NODE_ID_LOCAL_DRIVE:
                            break;
                        default: continue;
                    }
                    return L.GetNodeExpandPath(j);
                }

                for (int j = L.NodesCount - 1; j >= i; j--) // Prechadzam zprava do i
                {
                    INode N = L[i];
                    switch (N.ID)
                    {
                        case INode.NODE_ID_LOCAL_DRIVE:
                            break;
                        default: continue;
                    }
                    return L.GetNodeExpandPath(j);
                }
                return pPath; // Vratim original
            }
        }
        /// <summary>Vytvorenie menu zariadeni</summary>
        /// <param name="pParent">rodicovska kolekcia</param>
        /// <param name="pClickHandler">Click handler</param>
        public static void CreateDeviceMenu(System.Windows.Forms.ToolStripItemCollection pParent, EventHandler pClickHandler)
        {
            using (INodeList_ROOT L = new INodeList_ROOT()) // Vytvorim zoznam
            {
                L.FullExpand(); // Expandujem ho

                int C = L.NodesCount; // Ziskam pocet zaznamov
                for (int i = 0; i < C; i++) // Prejdem zoznam
                {
                    INode N = L[i]; // Ziskam node
                    string S = L.CreateDeviceMenuText(N); // Vytvorim text menu polozky
                    if (S == "") continue;

                    IToolStripMenuItem M = IToolStrip.CreateMenuItem(pParent, S, pClickHandler); // Vytvorim a vyplnim polozku menu
                    M.ImageIndex = N.DefaultImageIndex;
                    M.Tag = L.GetNodeExpandPath(i);
                }
            }
        }
        /// <summary>Ziskanie root ciest lokalnych zariadeni</summary>
        /// <returns>zoznam</returns>
        public static System.Collections.Generic.List<string> GetRootPathOfLocalDefices()
        {
            System.Collections.Generic.List<string> Result = new System.Collections.Generic.List<string>(); // Vytvorim zoznam
            using (INodeList_ROOT L = new INodeList_ROOT()) // Prechadzam nodelist root
            {
                L.FullExpand(null, false, false);
                foreach (INode N in L.FItems)
                {
                    if (N.ID == INode.NODE_ID_LOCAL_DRIVE) // Je to lokalne zariadenie?
                    {
                        if (((INodeData_LOCAL_DRIVE)N.NodeData).DrvInfo.IsReady) Result.Add(((INodeData_LOCAL_DRIVE)N.NodeData).DrvInfo.RootDirectory.ToString()); // Je to zariadenie pripravene?
                    }
                }
            }
            return Result; // Vratim najdene cesty
        }
    }
}
